using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;
using System.Net.Configuration;
using System.Configuration;

namespace Talentnet.Core.Utilities.Mail
{
    public struct MailServiceSettings
    {
        public SmtpAuthentication AuthenticationType { get; set; }
        public string Server { get; set; }
        public int Port { get; set; }
        public bool EnableSSL { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public string EmailContact { get; set; }
    }

    public class MailServices
    {
        public static bool SendEmail(string fromEmail, string toEmail, string mailSubject, string mailBody, MailServiceSettings settings)
        {
            // send email
            bool success = SendMail(fromEmail, toEmail, string.Empty, string.Empty, string.Empty, System.Net.Mail.MailPriority.Normal, mailSubject, mailBody,
                MailFormat.Text, Encoding.Unicode, string.Empty.Split('|'), settings.Server, settings.Port, settings.AuthenticationType, settings.Username, settings.Password, settings.EnableSSL);
            return success;
        }

        public static bool SendEmail(string emailFrom, string emailTo, string emailCC, string emailBCC, string emailSubject, string emailBody, string emailAttachmentFiles, MailFormat emailFormat, MailPriority emailPriority, MailServiceSettings emailSettings)
        {
            // send email
            bool success = MailServices.SendMail(emailFrom, emailTo, emailCC, emailBCC, string.Empty, emailPriority, emailSubject, emailBody, emailFormat,
                Encoding.Unicode, emailAttachmentFiles.Split(';'), emailSettings.Server, emailSettings.Port, emailSettings.AuthenticationType, emailSettings.Username, emailSettings.Password, emailSettings.EnableSSL);
            return success;
        }

        public static bool SendEmailWithDefaultSettings(string fromEmail, string toEmail, string mailSubject, string mailBody)
        {
            bool success = false;
            try
            {
                // get SMTP server info
                SmtpAuthentication smtpAuth = SmtpAuthentication.Anonymous;
                if (ConfigurationManager.AppSettings["smtpAuthentication"] != null)
                {
                    switch (ConfigurationManager.AppSettings["smtpAuthentication"])
                    {
                        case "0":
                            smtpAuth = SmtpAuthentication.Anonymous;
                            break;
                        case "1":
                            smtpAuth = SmtpAuthentication.Basic;
                            break;
                        case "2":
                            smtpAuth = SmtpAuthentication.NTLM;
                            break;
                    }
                }
                else
                {
                    throw new Exception("SmtpAuthentication is not configured! Please configure SmtpAuthentication, then restart PCC program.");
                }

                //int smtpPort = Convert.ToInt32(ConfigurationManager.AppSettings["smtpPort"]);
                int smtpPort = Int32.MinValue;
                if (ConfigurationManager.AppSettings["smtpPort"] != null) smtpPort = Convert.ToInt32(ConfigurationManager.AppSettings["smtpPort"]);
                else throw new Exception("SmtpPort is not configured! Please configure SmtpPort, then restart PCC program.");

                string smtpServer = string.Empty;
                if (ConfigurationManager.AppSettings["smtpUsername"] != null) smtpServer = ConfigurationManager.AppSettings["smtpServer"];
                else throw new Exception("SmtpServer is not configured! Please configure SmtpServer, then restart PCC program.");

                bool enableSSL = false;
                if (ConfigurationManager.AppSettings["enableSSL"] != null) enableSSL = (ConfigurationManager.AppSettings["enableSSL"] == "Yes" ? true : false);

                string smtpUsername = string.Empty;
                if (ConfigurationManager.AppSettings["smtpUsername"] != null) smtpUsername = ConfigurationManager.AppSettings["smtpUsername"];

                string smtpPassword = string.Empty;
                if (ConfigurationManager.AppSettings["smtpPassword"] != null) smtpPassword = ConfigurationManager.AppSettings["smtpPassword"];
                // send email
                success = MailServices.SendMail(fromEmail, toEmail, string.Empty, string.Empty, string.Empty, System.Net.Mail.MailPriority.Normal, mailSubject, mailBody,
                    MailFormat.Text, Encoding.Unicode, string.Empty.Split('|'), smtpServer, smtpPort, smtpAuth, smtpUsername, smtpPassword, enableSSL);
                return success;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Send email by using System.Net.Mail service.
        /// </summary>
        /// <param name="mailFrom"></param>
        /// <param name="mailTo"></param>
        /// <param name="Cc"></param>
        /// <param name="Bcc"></param>
        /// <param name="replyTo"></param>
        /// <param name="mailPriority"></param>
        /// <param name="subject"></param>
        /// <param name="body"></param>
        /// <param name="bodyFormat"></param>
        /// <param name="bodyEncoding"></param>
        /// <param name="attachments"></param>
        /// <param name="smtpServer"></param>
        /// <param name="smtpAuthentication"></param>
        /// <param name="smtpUsername"></param>
        /// <param name="smtpPassword"></param>
        /// <param name="smtpEnableSSL"></param>
        /// <returns>Return true if sending email is successful. Otherwise, return false.</returns>
        public static bool SendMail(string mailFrom, string mailTo, string Cc, string Bcc, string replyTo,
            MailPriority mailPriority, string subject, string body, MailFormat bodyFormat, Encoding bodyEncoding,
            string[] attachments, string smtpServer, int smtpPort, SmtpAuthentication smtpAuthentication,
            string smtpUsername, string smtpPassword, bool smtpEnableSSL)
        {
            bool success = false;
            // SMTP server configuration

            //SmtpSection smtpSettings = new SmtpSection();
            //if (smtpServer == "") smtpServer = smtpSettings.Network.Host;            
            //if (smtpUsername == "") smtpUsername = smtpSettings.Network.UserName;
            //if (smtpPassword == "") smtpPassword = smtpSettings.Network.Password;
            //if (mailFrom == "") mailFrom = smtpSettings.From;
            //translate semi-colon delimiters to commas as ASP.NET 2.0 does not support semi-colons
            mailTo = mailTo.Replace(";", ",");
            Cc = Cc.Replace(";", ",");
            Bcc = Bcc.Replace(";", ",");

            MailMessage objMail = null;
            try
            {
                objMail = new MailMessage(mailFrom, mailTo);
                if (Cc != "") objMail.CC.Add(Cc);
                if (Bcc != "") objMail.Bcc.Add(Bcc);
                if (replyTo != "") objMail.ReplyTo = new MailAddress(replyTo);
                objMail.Priority = mailPriority;
                objMail.IsBodyHtml = (bodyFormat == MailFormat.Html ? true : false);

                // include attachments.
                foreach (string filename in attachments)
                {
                    if (filename != "") objMail.Attachments.Add(new Attachment(filename));
                }
                objMail.Subject = subject;
                //objMail.SubjectEncoding = bodyEncoding;
                objMail.BodyEncoding = bodyEncoding;

                //added support for multipart html messages
                //add text part as alternate view
                //objMail.Body = Body
                AlternateView PlainView = AlternateView.CreateAlternateViewFromString(ConvertHtmlToText(body), null, "text/plain");
                objMail.AlternateViews.Add(PlainView);
                if (IsHtmlMail(body))
                {
                    AlternateView HtmlView = AlternateView.CreateAlternateViewFromString(body, null, "text/html");
                    objMail.AlternateViews.Add(HtmlView);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            if (objMail != null)
            {
                int SmtpPort = smtpPort;
                int portPos = smtpServer.IndexOf(":");
                if (portPos > -1)
                {
                    SmtpPort = Convert.ToInt32(smtpServer.Substring(portPos + 1, smtpServer.Length - portPos - 1));
                    smtpServer = smtpServer.Substring(0, portPos);
                }

                SmtpClient smtpClient = new SmtpClient();
                if (smtpServer != "") smtpClient.Host = smtpServer;
                smtpClient.Port = SmtpPort;
                switch (smtpAuthentication)
                {
                    case SmtpAuthentication.Anonymous:
                        break;
                    case SmtpAuthentication.Basic:
                        if (smtpUsername != "" && smtpPassword != "")
                        {
                            smtpClient.UseDefaultCredentials = false;
                            smtpClient.Credentials = new System.Net.NetworkCredential(smtpUsername, smtpPassword);
                        }
                        break;
                    case SmtpAuthentication.NTLM:
                        smtpClient.UseDefaultCredentials = true;
                        break;
                }
                smtpClient.EnableSsl = smtpEnableSSL;

                try
                {
                    smtpClient.Send(objMail);
                    success = true;
                }
                catch (SmtpException smtpEx)
                {
                    throw smtpEx;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    objMail.Dispose();
                }
            }

            return success;
        }


        /// <summary>
        /// Recognize if a string is HTML format.
        /// </summary>
        /// <param name="mailBody"></param>
        /// <returns>Return true if mailBody contains any html tags. Otherwise, return false.</returns>
        public static bool IsHtmlMail(string mailBody)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(mailBody, "<[^>]*>");
        }

        /// <summary>
        /// Convert a html string into raw text.
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public static string ConvertHtmlToText(string html)
        {
            string Content = html;
            Content = Content.Replace("<br />", System.Environment.NewLine);
            Content = Content.Replace("<br>", System.Environment.NewLine);
            Content = Content.Replace("<br/>", System.Environment.NewLine);
            Content = FormatText(Content, true);
            return StripTags(Content, true);
        }

        /// <summary>
        /// Replace all whitespace and html lines (<br/>).
        /// </summary>
        /// <param name="html">A html string which will be formated.</param>
        /// <param name="retainSpace">Replace by whitespace if retainSpace = true. Otherwise, replace by empty string.</param>
        /// <returns>A string without whitespace/new line.</returns>
        public static string FormatText(string html, bool retainSpace)
        {
            string brMatch = @"\s*<\s*[bB][rR]\s*/\s*>\s*";

            //Set up Replacement String
            string RepString;
            if (retainSpace) RepString = " ";
            else RepString = "";
            //Replace Tags by replacement String and return mofified string
            return System.Text.RegularExpressions.Regex.Replace(html, brMatch, RepString);
        }

        /// <summary>
        /// Replace all html tags by whitespace or empty string.
        /// </summary>
        /// <param name="html">A html string which will be formated.</param>
        /// <param name="retainSpace">Replace by whitespace if retainSpace = true. Otherwise, replace by empty string.</param>
        /// <returns>A string without html tags.</returns>
        public static string StripTags(string html, bool retainSpace)
        {
            //Set up Replacement String
            string RepString;
            if (retainSpace) RepString = " ";
            else RepString = "";

            //Replace Tags by replacement String and return mofified string
            return System.Text.RegularExpressions.Regex.Replace(html, "<[^>]*>", RepString);
        }

    }

    public enum MailFormat
    {
        Text,
        Html
    }

    public enum SmtpAuthentication
    {
        Anonymous,
        Basic,
        NTLM
    }
}
